/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Controllers;

import Algorithms.Comparaciones;
import Models.FacebookFriend;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import validadorxml.ValidadorXML;

/**
 *
 * Controla las funciones que se realizan en el Archivo XML de Facebook.
 * 
 * @author Daniel Ochoa John
 */
public class FacebookController 
{
    /**
     * VARIABLES DECLARATION
     */
    
    String RUTA_FACEBOOK;
    public String RUTA_SCHEMA = "xsd/FacebookFriendSchema.xsd";
    
    String RUTA_ABSOLUTA;
    private ArrayList<FacebookFriend> FBFriends = new ArrayList();
    float[][] track; 
    private ArrayList ocupados = new ArrayList();
    private ArrayList<FacebookFriend> FBFriendsM = new ArrayList();
    
    /**
     * 
     * Constructor de la clase FacebookController
     * 
     * @param Ruta Ruta física del archivo XML que contiene los datos de Facebook.
     */
    public FacebookController(String Ruta)
    {
        this.RUTA_FACEBOOK = Ruta;
        System.out.println(RUTA_SCHEMA);
        File f = new File(RUTA_SCHEMA);
        this.RUTA_ABSOLUTA = f.getAbsolutePath();
        f = null;
    }
    
    
    /*
     * VALIDA SI EL ARCHIVO XML CUMPLE EL SCHEMA
     */
    
    
    /**
     * 
     * Valida el archivo XML de Facebook contra su respectivo Schema
     * 
     * @return Retorna verdadero si el archivo es válido.<br> Falso si no es válido.
     */
    public boolean ValidarArchivoXML()
    {
        ValidadorXML validador = new ValidadorXML();
        validador.validarXMLconXSD(RUTA_ABSOLUTA, RUTA_FACEBOOK, false);
        return validador.es_valido();
    }
    
    
    
    /**
     * 
     * Lee el archivo XML que contiene los datos de Facebook, almacenando la información en un arreglo.
     * 
     * @return Retorna verdadero si la lectura fue exitosa.<br> Falso si la lectura no ha sido posible.
     */
    public boolean LeerArchivo()
    {
        try {
            SAXBuilder  builder = new SAXBuilder();
            File FacebookXMLFile = new File(this.RUTA_FACEBOOK);            
            Document document = (Document)builder.build(FacebookXMLFile);
            Element RootNode = document.getRootElement();
            List list = RootNode.getChildren("Friend");
            
            for(int i=0;i<list.size();i++)
            {
                Element node = (Element) list.get(i);
                String[] aux = node.getChildText("Birthday").split(",");
                String BDate = aux[0].trim();
                String BYear = null;
                try
                {
                    FacebookFriend FBFriend = new FacebookFriend
                            (node.getChildText("Name"),
                            node.getChildText("ID"),
                            node.getChildText("Username"),
                            node.getChildText("CommonFriends"),
                            node.getChildText("MutualPhotos"),
                            node.getChildText("CommonMessages"),
                            node.getChildText("ProfilePicture"),
                            BDate,node.getChildText("Sex"),
                            BYear,
                            node.getChildText("Relationship"));
                    FBFriends.add(FBFriend);
                }
                catch(Exception ex)
                {
                    return false;
                }
            }
        } catch (JDOMException ex) {
            return false;
        } catch (IOException ex) {
            return false;
        }
         return true;
    }
    
    
    
    
    
    /**
     * 
     * Analiza si es que en los datos de Facebook existen dos contactos iguales.<br> En otras palabras, analiza si
     * una misma persona tiene dos perfiles distintos.
     * 
     */
    public void AnalizaDuplicados()
    { 
        track = new float[FBFriends.size()][FBFriends.size()];
        for(int i = 0;i<this.FBFriends.size();i++)
        {
            FacebookFriend aux = this.FBFriends.get(i);
            
            for(int j = 0;j<this.FBFriends.size();j++)
            {
                FacebookFriend aux2 = this.FBFriends.get(j);
                
                if(i != j){
                
                    if((track[i][j] == 0)&&(track[j][i] == 0))
                    {
                    
                        float resultado = Comparaciones.CompararAmigos(aux, aux2);
                        
                        track[i][j] = resultado;
                        track[j][i] = resultado;
                        
                        if(resultado >= 0.8)
                        {
                            //System.out.println(aux.getName() + " V/S "+ aux2.getName());
                            this.ocupados.add(i);
                            this.ocupados.add(j);
                            this.FBFriendsM.add(UnirDuplicados(aux,aux2));
                        }                      
                    }
                
                }
            }
            
            if(!(this.ocupados.contains(i)))
            {
                this.FBFriendsM.add(FBFriends.get(i));
            }
            
        }
    }
    
    
    
    /**
     * 
     * Une dos amigos de Facebook en uno solo.<br>Este método se utiliza para unir amigos si es que se detecta algún duplicado.
     * 
     * @param A Amigo de Facebook 1
     * @param B Amigo de Facebook 2
     * @return Un amigo de Facebook con la información unida desde A y B.
     */
    private FacebookFriend UnirDuplicados(FacebookFriend A,FacebookFriend B)
    {
        //Datos que serán comparados
        
        String Name;
        long ID;
        String Username;
        int CommonFriends;
        int CommonMessages;
        String ProfilePicture;
        String MutualPhotos;
        String BirthdayDate;
        String BirthdayYear = null;
        String Sex;
        String Relationship;
        
        //Se asignan los datos, segun la información mas completa y reciente.
        
        Sex = A.getSex();
        CommonFriends = Math.max(A.getCommonFriends(), B.getCommonFriends());
        CommonMessages = A.getCommonMessages() + B.getCommonMessages();
        int MutualP = Integer.valueOf(A.getMutualPhotos()) + Integer.valueOf(B.getMutualPhotos());
        MutualPhotos = String.valueOf(MutualP);
        
        
        if(A.getName().length() >= B.getName().length())
        {
            Name = A.getName();
        }
        else
        {
            Name = B.getName();
        }
        
        if(A.getID() > B.getID())
        {
            ProfilePicture = A.getProfilePicture();
            ID = A.getID();
            Username = A.getUsername();
            Relationship = A.getRelationship();
            if(!"".equals(A.getBirthdayDate().trim()))
            {
                BirthdayDate = A.getBirthdayDate();
            }
            else
            {
                BirthdayDate = B.getBirthdayDate();
            }
            
            
        }
        else
        {
            ID = B.getID();
            Username = B.getUsername();
            ProfilePicture = B.getProfilePicture();
            Relationship = B.getRelationship();
            if(!"".equals(B.getBirthdayDate().trim()))
            {
                BirthdayDate = B.getBirthdayDate();
            }
            else
            {
                BirthdayDate = A.getBirthdayDate();
            }
            
        }
        
        FacebookFriend Merged = new FacebookFriend
                (
                    Name,
                    String.valueOf(ID),
                    Username,
                    String.valueOf(CommonFriends),
                    MutualPhotos,
                    String.valueOf(CommonMessages),
                    ProfilePicture,
                    BirthdayDate,
                    Sex,
                    null,
                    Relationship
                );
        
        //Merged.Escribir();
        
        return Merged;
        
    }

    /**
     * 
     * Retorna la lista completa de amigos de Facebook ya sin contactos duplicados.
     * 
     * @return Una lista de objetos FacebookFriend, que representa a todos los amigos de Facebook del usuario.
     */
    public ArrayList<FacebookFriend> getFBFriendsM() {
        return FBFriendsM;
    }

    public String getRUTA_SCHEMA() {
        return RUTA_SCHEMA;
    }
    
    
    
}
